home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_13_08 / phillip2 / scale.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-25  |  17.1 KB  |  559 lines

  1.  
  2.  
  3.     /***********************************************
  4.     *
  5.     *       file d:\cips\scale.c
  6.     *
  7.     *       Functions: This file contains
  8.     *          zoom_image_array
  9.     *          shrink_image_array
  10.     *          interpolate_pixel
  11.     *          average_pixel
  12.     *          median_pixel
  13.     *          get_scaling_options
  14.     *          blank_image_array
  15.     *
  16.     *       Purpose:
  17.     *          These functions implement image array
  18.     *          zooming (enlarging) and shrinking.
  19.     *
  20.     *       External Calls:
  21.     *          wtiff.c - round_off_image_size
  22.     *                    create_file_if_needed
  23.     *                    write_array_into_tiff_image
  24.     *          tiff.c - read_tiff_header
  25.     *          rtiff.c - read_tiff_image
  26.     *          numcvrt.c - get_integer
  27.     *          filter.c - median_of
  28.     *
  29.     *       Modifications:
  30.     *          8 April 1992 - created
  31.     *
  32.     *************************************************/
  33.  
  34. #include "cips.h"
  35.  
  36.      /*******************************************
  37.      *
  38.      *   zoom_image_array(...
  39.      *
  40.      *   This function zooms in on an input
  41.      *   image array.  It zooms by enlarging
  42.      *   an input image array and writing the
  43.      *   resulting image arrays to an output
  44.      *   image file.  It can zoom or enlarge by
  45.      *   a factor of 2 or 4.
  46.      *
  47.      *   You can zoom or enlarge an image array
  48.      *   by using either the replication or
  49.      *   interpolation methods.
  50.      *
  51.      *******************************************/
  52.  
  53.  
  54. zoom_image_array(in_name, out_name, the_image, out_image,
  55.           il, ie, ll, le, scale, method)
  56.    char   in_name[], out_name[], method[];
  57.    int    il, ie, ll, le, scale;
  58.    short  the_image[ROWS][COLS],
  59.           out_image[ROWS][COLS];
  60. {
  61.    int    A, B, a, b, count, factor, 
  62.           i, j, length, width;
  63.    struct tiff_header_struct image_header;
  64.  
  65.            /******************************************
  66.            *
  67.            *   Check the scale factor.  If it is not
  68.            *   a valid factor (2 or 4), then set
  69.            *   it to 2.
  70.            *
  71.            ******************************************/
  72.  
  73.    factor = scale;
  74.    if(factor != 2 &&
  75.       factor != 4) factor = 2;
  76.  
  77.    create_file_if_needed(in_name, out_name, out_image);
  78.  
  79.       /*******************************************
  80.       *
  81.       *   Let me try to explain the nested loops
  82.       *   shown below.
  83.       *
  84.       *   We will enlarge the_image by the factor.
  85.       *   Therefore, we want to divide the_image
  86.       *   into parts of size ROWS/factor by
  87.       *   COLS/factor.  We will loop through
  88.       *   the_image parts ROWS/factor and COLS/factor
  89.       *   using the loops over i and j.
  90.       *
  91.       *   We divided the_image into parts so we must
  92.       *   include all of these parts.  That is why we
  93.       *   do the loops over A and B.  There are
  94.       *   factor*factor parts.
  95.       *
  96.       *   Finally, we do the loops over a and b.
  97.       *   We must replicate every element in the_image
  98.       *   factor*factor times and put these into
  99.       *   out_image.  The a and b loops perform this
  100.       *   task.
  101.       *
  102.       *   The equations inside the []'s for
  103.       *   the_image and out_image are also confusing.
  104.       *   If you work them out, you'll see that we
  105.       *   are bouncing through the image arrays
  106.       *   and fitting the pixels into the right
  107.       *   places.
  108.       *
  109.       *   The final proof is that this works.
  110.       *
  111.       *   One final note:  the factor should divide
  112.       *   evenly into ROWS.  For example, ROWS=100
  113.       *   so using a factor of 8 is not good.
  114.       *   100/8 = 12.5 and this leave you with
  115.       *   an empty strip along the right and
  116.       *   bottom edges of the out_image.
  117.       *
  118.       *******************************************/
  119.  
  120.            /*****************************************
  121.            *
  122.            *   Replication method
  123.            *
  124.            ******************************************/
  125.  
  126.    if(method[0] == 'r' || method[0] == 'R'){
  127.       read_tiff_image(in_name, the_image, 
  128.                       il, ie, ll, le);
  129.       count = 1;
  130.       for(A=0; A<factor; A++){
  131.        for(B=0; B<factor; B++){
  132.         for(i=0; i<ROWS/factor; i++){
  133.          for(j=0; j<COLS/factor; j++){
  134.           for(a=0; a<factor; a++){
  135.            for(b=0; b<factor; b++){
  136.              out_image[factor*i+a][factor*j+b] =
  137.               the_image[i+A*ROWS/factor][j+B*COLS/factor];
  138.            }  /* ends loop over b */
  139.           }  /* ends loop over a */
  140.          }  /* ends loop over j */
  141.         }  /* ends loop over i */
  142.         printf("\nzooming replication %3d of %3d",
  143.                count++, factor*factor);
  144.         write_array_into_tiff_image(out_name, out_image,
  145.             1+A*ROWS, 1+B*COLS, 101+A*ROWS, 101+B*COLS);
  146.        }  /* ends loop over B */
  147.       }  /* ends loop over A */
  148.    }  /* ends replication method */
  149.  
  150.            /***************************
  151.            *
  152.            *   Interpolation method
  153.            *
  154.            ****************************/
  155.  
  156.    if(method[0] == 'i' || method[0] == 'I'){
  157.       read_tiff_image(in_name, the_image,
  158.                       il, ie, ll, le);
  159.       count = 1;
  160.       for(A=0; A<factor; A++){
  161.          for(B=0; B<factor; B++){
  162.           for(i=0; i<ROWS/factor; i++){
  163.            for(j=0; j<COLS/factor; j++){
  164.             for(a=0; a<factor; a++){
  165.              for(b=0; b<factor; b++){
  166.                 out_image[factor*i+a][factor*j+b] =
  167.                   interpolate_pixel(the_image, A, B,
  168.                               i, j, a, b, factor);
  169.              }  /* ends loop over b */
  170.             }  /* ends loop over a */
  171.            }  /* ends loop over j */
  172.           }  /* ends loop over i */
  173.        printf("\nzooming interpolation %3d of %3d",
  174.                      count++, factor*factor);
  175.        write_array_into_tiff_image(out_name, out_image,
  176.                  1+A*ROWS, 1+B*COLS,
  177.                  101+A*ROWS, 101+B*COLS);
  178.      }  /* ends loop over B */
  179.     }  /* ends loop over A */
  180.    }  /* ends interpolation method */
  181.  
  182.  
  183. }  /* ends zoom_image_array */
  184.  
  185.  
  186.  
  187.  
  188.  
  189.     /***********************************************
  190.     *
  191.     *    interpolate_pixel(...
  192.     *
  193.     *    This function interpolates between pixel
  194.     *    values and returns the interlopated value.
  195.     *
  196.     ***********************************************/
  197.  
  198. interpolate_pixel(the_image, A, B, i, j, a, b, factor)
  199.    int   A, B, a, b, factor, i, j;
  200.    short the_image[ROWS][COLS];
  201. {
  202.    int   num, x = 0, y = 0;
  203.    short diff, result;
  204.  
  205.    if(a > 0) y = 1;
  206.    if(b > 0) x = 1;
  207.    diff = 
  208.       the_image[y+i+A*ROWS/factor][x+j+B*COLS/factor] -
  209.       the_image[i+A*ROWS/factor][j+B*COLS/factor];
  210.  
  211.           /******************************************
  212.           *
  213.           * If you are at the edge of the input image
  214.           * array, then you cannot interpolate to the
  215.           * next point because there is no next point.
  216.           * Therefore, set the diff to 0.
  217.           *
  218.           *******************************************/
  219.  
  220.    if((y+i+A*ROWS/factor) >= ROWS) diff = 0;
  221.    if((x+j+B*COLS/factor) >= COLS) diff = 0;
  222.  
  223.    num = a+b;
  224.    if(num > factor) num = factor;
  225.    result = the_image[i+A*ROWS/factor][j+B*COLS/factor] +
  226.             num*diff/factor;
  227.    return(result);
  228. }  /* ends interpolate_pixel */
  229.  
  230.  
  231.  
  232.  
  233.  
  234.      /*******************************************
  235.      *
  236.      *   shrink_image_array(...
  237.      *
  238.      *   This function shrinks a part of an
  239.      *   image.  It takes a part of an input
  240.      *   image (described by il1, ie1, ll1, le1)
  241.      *   shrinks a 200x200 or 400x400 area down
  242.      *   to a 100x100 array, and writes this result
  243.      *   to an output file.  The location in the
  244.      *   output file is described by il2, ie2,
  245.      *   ll2, le2.
  246.      *
  247.      *   You can shrink the input image area
  248.      *   by using either the averaging, median,
  249.      *   or corner method.
  250.      *
  251.      *******************************************/
  252.  
  253. shrink_image_array(in_name, out_name, 
  254.           the_image, out_image,
  255.           il1, ie1, ll1, le1, il2, ie2, ll2, le2,
  256.           scale, method)
  257.    char   in_name[], out_name[], method[];
  258.    int    il1, ie1, ll1, le1,
  259.           il2, ie2, ll2, le2, scale;
  260.    short  the_image[ROWS][COLS],
  261.           out_image[ROWS][COLS];
  262. {
  263.    int    A, B, a, b, count, factor, 
  264.           i, j, length, width;
  265.    struct tiff_header_struct image_header;
  266.  
  267.            /******************************************
  268.            *
  269.            *   Check the scale factor.  If it is not
  270.            *   a valid factor (2 or 4), then set
  271.            *   it to 2.
  272.            *
  273.            ******************************************/
  274.  
  275.    factor = scale;
  276.    if(factor != 2 &&
  277.       factor != 4) factor = 2;
  278.  
  279.    create_file_if_needed(in_name, out_name, out_image);
  280.  
  281.    read_tiff_header(in_name, &image_header);
  282.  
  283.       /**********************************************
  284.       *
  285.       *   Let me try to explain the nested loops
  286.       *   shown below.
  287.       *
  288.       *   We will shrink the_image by the factor.
  289.       *   Therefore, we want to read in factor*factor
  290.       *   image arrays and produce one ROWS by COLS
  291.       *   array for writing to disk.
  292.       *   That is why we loop over A and B.
  293.       *
  294.       *   We want to set every pixel in the out_image
  295.       *   array so we loop over i and j.
  296.       *
  297.       *   The equations inside the out_image []'s
  298.       *   look a little strange.  What we are doing is
  299.       *   setting every element and moving over every
  300.       *   time through the loops over A and B.  
  301.       *   The first loop is for i=0,49 then i=50,99 
  302.       *   for a factor=2 and ROWS=100.
  303.       *
  304.       *   The final proof is that this works.
  305.       *
  306.       *   One final note:  the factor should divide
  307.       *   evenly into ROWS.  For example, ROWS=100
  308.       *   so using a factor of 8 is not good.
  309.       *   100/8 = 12.5 and this leave you with
  310.       *   an empty strip along the right and
  311.       *   bottom edges of the out_image.
  312.       *
  313.       ************************************************/
  314.  
  315.            /********************************
  316.            *
  317.            *   Corner method
  318.            *
  319.            *********************************/
  320.  
  321.    if(method[0] == 'c' || method[0] == 'C'){
  322.       count = 1;
  323.       for(A=0; A<factor; A++){
  324.        for(B=0; B<factor; B++){
  325.         printf("\n shrinking by corner %3d of %3d",
  326.                      count++, factor*factor);
  327.         if(image_header.image_length < ll1+A*ROWS   ||
  328.            image_header.image_width  < le1+B*COLS)
  329.            blank_image_array(the_image);
  330.         else
  331.            read_tiff_image(in_name, the_image,
  332.                            il1+A*ROWS, ie1+B*COLS,
  333.                            ll1+A*ROWS, le1+B*COLS);
  334.         for(i=0; i<ROWS/factor; i++){
  335.          for(j=0; j<COLS/factor; j++){
  336.             out_image[i+A*ROWS/factor][j+B*COLS/factor] =
  337.                      the_image[factor*i][factor*j];
  338.          }  /* ends loop over j */
  339.         }  /* ends loop over i */
  340.        }  /* ends loop over B */
  341.       }  /* ends loop over A */
  342.       write_array_into_tiff_image(out_name, out_image,
  343.                                   il2, ie2, ll2, le2);
  344.    } /* ends corner method */
  345.  
  346.            /******************************
  347.            *
  348.            *   Average Method
  349.            *
  350.            ******************************/
  351.  
  352.    if(method[0] == 'a' || method[0] == 'A'){
  353.       count = 1;
  354.       for(A=0; A<factor; A++){
  355.        for(B=0; B<factor; B++){
  356.         printf("\n shrinking by average %3d of %3d",
  357.                      count++, factor*factor);
  358.         if(image_header.image_length < ll1+A*ROWS   ||
  359.            image_header.image_width  < le1+B*COLS)
  360.            blank_image_array(the_image);
  361.         else
  362.            read_tiff_image(in_name, the_image,
  363.                           il1+A*ROWS, ie1+B*COLS,
  364.                           ll1+A*ROWS, le1+B*COLS);
  365.         for(i=0; i<ROWS/factor; i++){
  366.          for(j=0; j<COLS/factor; j++){
  367.           out_image[i+A*ROWS/factor][j+B*COLS/factor] =
  368.                 average_pixel(the_image, factor, i, j);
  369.          }  /* ends loop over j */
  370.         }  /* ends loop over i */
  371.        }  /* ends loop over B */
  372.       }  /* ends loop over A */
  373.       write_array_into_tiff_image(out_name, out_image,
  374.                                   il2, ie2, ll2, le2);
  375.    } /* ends average method */
  376.  
  377.            /************************
  378.            *
  379.            *   Median Method
  380.            *
  381.            *************************/
  382.  
  383.    if(method[0] == 'm' || method[0] == 'M'){
  384.       count = 1;
  385.       for(A=0; A<factor; A++){
  386.        for(B=0; B<factor; B++){
  387.         printf("\n shrinking by median %3d of %3d",
  388.                      count++, factor*factor);
  389.         if(image_header.image_length < ll1+A*ROWS   ||
  390.            image_header.image_width  < le1+B*COLS)
  391.            blank_image_array(the_image);
  392.         else
  393.            read_tiff_image(in_name, the_image,
  394.                            il1+A*ROWS, ie1+B*COLS,
  395.                            ll1+A*ROWS, le1+B*COLS);
  396.         for(i=0; i<ROWS/factor; i++){
  397.          for(j=0; j<COLS/factor; j++){
  398.           out_image[i+A*ROWS/factor][j+B*COLS/factor] =
  399.                 median_pixel(the_image, factor, i, j);
  400.          }  /* ends loop over j */
  401.         }  /* ends loop over i */
  402.        }  /* ends loop over B */
  403.       }  /* ends loop over A */
  404.       write_array_into_tiff_image(out_name, out_image,
  405.                                   il2, ie2, ll2, le2);
  406.    } /* ends median method */
  407.  
  408. }  /* ends shrink_image_array */
  409.  
  410.  
  411.  
  412.  
  413.  
  414.     /***********************************************
  415.     *
  416.     *   average_pixel(...
  417.     *
  418.     *   This function calculates the average
  419.     *   pixel value of a factor x factor array
  420.     *   of pixels inside the the_image array.
  421.     *   The coordinates i and j point to the upper
  422.     *   left hand corner of the small array.
  423.     *
  424.     ***********************************************/
  425.  
  426. average_pixel(the_image, factor, i, j)
  427.    int   factor, i, j;
  428.    short the_image[ROWS][COLS];
  429. {
  430.    int a, b, result = 0;
  431.  
  432.    for(a=0; a<factor; a++)
  433.       for(b=0; b<factor; b++)
  434.          result = result + 
  435.                   the_image[factor*i+a][factor*j+a];
  436.    result = result/(factor*factor);
  437.  
  438.    return(result);
  439. }  /* ends average_pixel */
  440.  
  441.  
  442.  
  443.  
  444.  
  445.     /***********************************************
  446.     *
  447.     *   median_pixel(...
  448.     *
  449.     *   This function calculates the median
  450.     *   pixel value of a factor x factor array
  451.     *   of pixels inside the the_image array.
  452.     *   The coordinates i and j point to the upper
  453.     *   left hand corner of the small array.
  454.     *
  455.     ***********************************************/
  456.  
  457. median_pixel(the_image, factor, i, j)
  458.    int   factor, i, j;
  459.    short the_image[ROWS][COLS];
  460. {
  461.    int   a, b, count, ff, result = 0;
  462.    short *elements;
  463.  
  464.    ff       = factor*factor;
  465.    elements = (short *) malloc(ff * sizeof(short));
  466.  
  467.      count = 0;
  468.    for(a=0; a<factor; a++){
  469.          for(b=0; b<factor; b++){
  470.             elements[count] = 
  471.                the_image[factor*i+a][factor*j+b];
  472.               count++;
  473.         }
  474.      }
  475.  
  476.    result = median_of(elements, &ff);
  477.    free(elements);
  478.    return(result);
  479.  
  480. }  /* ends median_pixel */
  481.  
  482.  
  483.  
  484.  
  485.  
  486.     /***********************************************
  487.     *
  488.     *    get_scaling_options(...
  489.     *
  490.     *    This function queries the user for the
  491.     *    parameters needed to perform scaling.
  492.     *
  493.     ***********************************************/
  494.  
  495. get_scaling_options(zoom_shrink, scale, method)
  496.    int *scale;
  497.    char method[], zoom_shrink[];
  498. {
  499.    int not_finished = 1, response;
  500.  
  501.    while(not_finished){
  502.       printf("\n\t1. Zoom or Shrink is - %s", 
  503.              zoom_shrink);
  504.       printf("\n\t2. Scale factor is %d", *scale);
  505.       printf("\n\t3. Scaling Method is - %s", method);
  506.       printf(
  507.       "\n\t     Replication or Interpolation for Zooming"
  508.       "\n\t     Averaging Median or Corner for Shrinking");
  509.       printf("\n\n\tEnter choice (0 = no change) _\b");
  510.       get_integer(&response);
  511.  
  512.       if(response == 0){
  513.         not_finished = 0;
  514.       }
  515.  
  516.       if(response == 1){
  517.          printf("\nEnter Zoom or Shrink (z or s) __\b");
  518.          gets(zoom_shrink);
  519.       }
  520.  
  521.       if(response == 2){
  522.          printf("\nEnter Scale Factor (2 or 4) __\b");
  523.          get_integer(scale);
  524.       }
  525.  
  526.       if(response == 3){
  527.          printf("\nEnter Scaling Method: "
  528.             "Replication or Interpolation for Zooming"
  529.             "\n                      "
  530.             "Averaging Median or Corner for Shrinking"
  531.             "\n\t__\b");
  532.          gets(method);
  533.       }
  534.  
  535.    }  /* ends while not_finished */
  536. }  /* ends get_scaling_options */
  537.  
  538.  
  539.  
  540.  
  541.  
  542.     /***********************************************
  543.     *
  544.     *   blank_image_array(...
  545.     *
  546.     *   This function blanks out an image array
  547.     *   by filling it with zeros.
  548.     *
  549.     ***********************************************/
  550.  
  551. blank_image_array(image)
  552.    short image[ROWS][COLS];
  553. {
  554.    int i, j;
  555.    for(i=0; i<ROWS; i++)
  556.       for(j=0; j<COLS; j++)
  557.          image[i][j] = 0;
  558. }  /* ends blank_image_array */
  559.